package com.example.myapplication.ui;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.example.myapplication.R;
import com.example.myapplication.config.TagInfo;
import com.example.myapplication.model.IPInfo;
import com.pc_rfid.api.OnUsbListener;
import com.pc_rfid.api.PC_API;
import com.pc_rfid.api.RFdata;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class Door extends Activity {

    /**
     * PC_GetInOutInfo  进出人数
     *      Data[0-3]：人员进数量；低字节在前。
     *      Data[4-7]：人员出数量；低字节在前。
     * PC_ClearInOutInfo  清空进出人数，  1 进数量归零  2 出数量归零  3 进，出数量都归零
     */
    PC_API pcApi = new PC_API();
    String TAG = "==================";
    Context context;

    private RFdata rf=null;
    boolean iscmd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_door);
        context = this;
        initDoor();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
//        PC_API.USB_exit();
    }

    Handler han = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    };


    private void initDoor(){
        han.postDelayed(new Runnable() {
            @Override
            public void run() {

            }
        },100);
        han.removeCallbacks(new Runnable() {
            @Override
            public void run() {

            }
        });
        rf=new RFdata();
        iscmd=false;
//        PC_API.USB_init(this);//程序开始时执行，在USB监听及读写之前要先执行，否则操作无效
//        //USB插拔监听
//        PC_API.setOnUsbListener(new OnUsbListener() {
//            @Override
//            public void onStateChanged(UsbDevice usbDevice, boolean b) {
//                Log.d(TAG, String.format("VID=%04X,PID=%04X",usbDevice.getVendorId(),usbDevice.getProductId()));
//                if(b){
//                    //播放系统通知提示音
//                    Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//                    Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
//                    r.play();
//                    Toast.makeText(context,"USB：检测到设备接入",Toast.LENGTH_SHORT).show();
//                    //这里可以直接利用PC_API.PC_OpenUSB(usbDevice)打开设备
//                }else{
//                    Toast.makeText(context,"USB：设备断开连接",Toast.LENGTH_SHORT).show();
//                }
//            }
//        });
    }

    IPInfo ipTemp;
    public void onClickVoid(View v){
        int id = v.getId();
        Intent it = new Intent();
        if(id == R.id.button1){
            iscmd=true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    action1();
                }
            }).start();
        }else if(id == R.id.button2){
            pcApi.PC_Close();
            iscmd=false;
        }else if(id == R.id.button3){
            new Thread(){
                @Override
                public void run() {
                    if(pcApi.PC_NetWriteDeviceInfo(rf,ipTemp.ipaddr,ipTemp.subnetMask,ipTemp.gateway)){
                        log("IP修改成功\n\n");
                        //设备IP信息本质上没有改动，所以不需要重新配置网络
                    }else{
                        log("IP修改失败\n\n");
                    }
                }
            }.start();
        }else if(id == R.id.button4){
            new Thread(){
                @Override
                public void run() {
                    if(pcApi.PC_GetInOutInfo(rf)){
                        int[] tttemp = new int[8];
                        String in = "";
                        String out = "";
                        for(int i = 0 ; i < 8 ; i ++){
                            tttemp[i] = rf.RecvData[6+i] & 0xFF;
                        }
                        in += Integer.toHexString(tttemp[3]);
                        in += Integer.toHexString(tttemp[2]);
                        in += Integer.toHexString(tttemp[1]);
                        in += Integer.toHexString(tttemp[0]);


                        int inPerson = tttemp[0] + tttemp[1] * 256 + tttemp[2]  * 256 * 256+ tttemp[3] *256*256*256;
                        int outPerson = tttemp[4] + tttemp[5] * 256 + tttemp[6]  * 256 * 256+ tttemp[7] *256*256*256;
                        log("Test: 进馆人数为：" +inPerson + "   出关人数为："+ outPerson);
                    }else{

                    }
                }
            }.start();
        }else if(id == R.id.button5){
            if(pcApi.PC_ClearInOutInfo(rf,(byte)1)){
                log("清空成功\n\n");
            }else{
                log("清空失败\n\n");
            }
        }else if(id == R.id.button6){
            new Thread(){
                @Override
                public void run() {
                    if(pcApi.relayControl(rf,0)){
                        log("继电器打开成功！！！！");
                    }else{
                        log("继电器打开失败~~~~");
                    }
                }
            }.start();
        }else{

        }
    }

    private void action1(){
        iscmd=true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                //网络搜索设备
                List<IPInfo> ip_list=ScanIP(pcApi);
                if(ip_list.size()>0){
                    log("设备数量"+ip_list.size()+"\n\n");

                    //网络修改设备IP、子网掩码、网关
                    IPInfo ip_1=ip_list.get(0);
                    if(pcApi.PC_OpenNET(ip_1.getIP(),6688)) {//配置网络
                        ipTemp = ip_1;
                        log("配置网络【"+ip_1.getIP()+":6688】成功\n");
//                                //这里演示用法，IP信息不做改动，把获取的信息设置回去
//                                ip_1.ipaddr[2] = 3;
//                                ip_1.gateway[2] = 3;
//                                if(pcApi.PC_NetWriteDeviceInfo(rf,ip_1.ipaddr,ip_1.subnetMask,ip_1.gateway)){
//                                    log.Text(LOG_ADD, "IP修改成功\n\n");
//                                    //设备IP信息本质上没有改动，所以不需要重新配置网络
//                                    runCmd(pcApi);
//                                }else{
//                                    log.Text(LOG_ADD, "IP修改失败\n\n");
//                                }
                    }
                } else{
                    log("未连接设备\n");
                }
            }
        }).start();
    }

    private void action2(){
    }

    private synchronized void exe(){
    }

    private void log(String content){
        Log.e(TAG, content);
    }

    /**
     * 网络广播搜索设备（同网段）
     * @param api PC_API实例对象
     * @return 设备IP列表
     */
    public List<IPInfo> ScanIP(PC_API api){
        List<IPInfo> IP_list=new ArrayList<IPInfo>();
        log("正在搜索设备...\n");
        if(api.PC_OpenNET("255.255.255.255",6688)) {//配置网络，广播搜索
            //搜索ip
            if (api.PC_NetScanDeviceInfo(rf)) {
                IPInfo ip_1=new IPInfo(rf.RecvData);//解析
                IP_list.add(ip_1);
                showSendReceiveData(rf);
                log( ip_1.get_info() + "\n");
                //成功接收了一个包，接着继续尝试接收，直到超时（2秒）
                while (api.PC_Receive(rf)) {
                    IPInfo ip_2=new IPInfo(rf.RecvData);//解析
                    IP_list.add(ip_2);
                    showReceiveData(rf.RecvData);
                    log(ip_2.get_info() + "\n");
                }
            }
        }
        return IP_list;
    }

    /**
     * 执行命令
     */
    private void runCmd(PC_API api){
        RFdata rf=new RFdata();
        byte []data=null;
        byte []UID=null;
        byte b_DSFID=0X00;
        byte b_AFI=0X00;
        boolean isUploadAntNum=false;//上传天线编号

        //打开设备命令
        if(api.PC_OpenDevice(rf)){
            showSendReceiveData(rf);
            log("打开设备成功");
        }else{
            log("打开设备失败");
            return;
        }

        //获取设备信息命令
        if(api.PC_GetDeviceInfoVersion(rf)){
            showSendReceiveData(rf);
            log("获取设备信息成功");
        }else{
            log("获取设备信息失败");
            return;
        }

        //读配置块3命令
        if(api.PC_ReadCfgBlock(rf, (byte) 3)){
            showSendReceiveData(rf);
            log("读配置块3成功\n\n");
            //记录配置块数据，保证写配置时不更改配置
            data=new byte[8];
            for(int k=0;k<8;k++)
            {
                data[k]=rf.RecvData[k+6];
            }
            //记录上传天线编号标识
            if((data[0]>>>4&0x01)==1)
            {
                isUploadAntNum=true;//网络盘点解析天线口号用到
            }
        }else{
            log("读配置块3失败\n");
            return;
        }

        //写配置块3命令
        if(data!=null&&api.PC_WriteCfgBlock(rf,data, (byte) 3)){
            showSendReceiveData(rf);
            log("写配置块3成功\n\n");
            data=null;
        }else{
            log("写配置块3失败\n");
            return;
        }

        //保存配置块命令
        if(api.PC_SaveCfgBlock(rf, (byte) 0)){
            showSendReceiveData(rf);
            log("保存配置块成功\n\n");
        }else{
            log("保存配置块失败\n");
            return;
        }

        //噪音检测命令
        if(api.PC_NoiseCheck(rf,(byte)0)){
            showSendReceiveData(rf);
            log("噪音检测成功\n\n");
        }else{
            log("噪音检测失败\n");
            return;
        }

        //打开射频命令
        if(api.PC_Open_CloseRFPower(rf,(byte)1)){
            showSendReceiveData(rf);
            log("打开射频成功\n\n");
        }else{
            log("打开射频失败\n");
            return;
        }

        //关闭射频命令
        if(api.PC_Open_CloseRFPower(rf,(byte)0)){
            showSendReceiveData(rf);
            log("关闭射频成功\n\n");
        }else{
            log("关闭射频失败\n");
            return;
        }

        //蜂鸣器闪烁命令
        if(api.PC_HardwareControl(rf,(byte)1,(byte)0x80,(byte)0)){
            showSendReceiveData(rf);
            log("蜂鸣器闪烁成功\n\n");
        }else{
            log("蜂鸣器闪烁失败\n");
            return;
        }

        //继电器闪烁命令
        if(api.PC_HardwareControl(rf,(byte)1,(byte)1,(byte)0)){
            showSendReceiveData(rf);
            log("继电器闪烁成功\n\n");
        }else{
            log("继电器闪烁失败\n");
            return;
        }

        //盘点命令
        List<TagInfo> tag_list=ScanTab(api,0,isUploadAntNum);
        if(tag_list!=null){
            log("盘点成功\n");
            int len=tag_list.size();
            log(String.format("标签数量%d\n\n",len));
            if(len==0){
                log("检测完成！");
                return;
            }
            UID=tag_list.get(0).UID;//记录第一个标签的UID，读写卡命令用到
        }else{
            log("盘点失败\n");
            return;
        }

        //打开天线口命令，读写标签之前要打开标签所在的天线口
        if(api.PC_OpenAnt_One(rf,(byte)1)){
            showSendReceiveData(rf);
            log("打开天线口1成功\n\n");
        }else{
            log("打开天线口1失败\n");
            return;
        }

        //获取标签信息命令
        if(api.PC_GetOneTagInfo(rf,UID,(byte)1)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0) {
                log("获取标签信息成功\n\n");
                //记录DSFID和AFI，
                b_DSFID = rf.RecvData[15];
                b_AFI = rf.RecvData[16];
            }else{
                log("获取标签信息失败\n");
                return;
            }
        }else{
            log("获取标签信息失败\n");
            return;
        }

        //读单个数据块命令
        if(api.PC_ReadCardOneBlock(rf,UID,(byte)1,(byte)0,(byte)0)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0) {
                log("读数据块0成功\n\n");
                //记录数据块
                data = new byte[4];
                for (int k = 0; k < 4; k++) {
                    data[k] = rf.RecvData[8 + k];
                }
            }else{
                log("读数据块0失败\n");
                return;
            }
        }else{
            log("读数据块0失败\n");
            return;
        }

        //写单个数据块命令
        if(data!=null&&api.PC_WriteCardOneBlock(rf,UID,(byte)1,(byte)0,data)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0) {
                log("写数据块0成功\n\n");
                data = null;
            }else{
                log("写数据块0失败\n");
                return;
            }
        }else{
            log("写数据块0失败\n");
            return;
        }

        //读多个数据块命令
        if(api.PC_ReadCardMultBlock(rf,UID,(byte)1,(byte)0,(byte)2)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0) {
                if (api.GetLinkType() != PC_API.NET) {
                    //非UDP传输方式，还有一个结束包
                    RFdata rf_1 = new RFdata();
                    if (api.PC_Receive(rf_1)) {
                        showReceiveData(rf_1.RecvData);

                    } else {
                        log("读数据块0~2失败\n");
                        return;
                    }
                }
                log("读数据块0~2成功\n\n");
                //记录数据块
                data = new byte[12];
                for (int k = 0; k < 4; k++) {
                    data[k] = rf.RecvData[k + 17];
                    data[k + 4] = rf.RecvData[k + 17 + 5];
                    data[k + 8] = rf.RecvData[k + 17 + 10];
                }
            }else{
                log("读数据块0~2失败\n");
                return;
            }
        }else{
            log("读数据块0~2失败\n");
            return;
        }

        //写多个数据块命令
        if(data!=null&&api.PC_WriteCardMultBlock(rf,UID,(byte)1,(byte)0,(byte)2,data)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0) {
                log("写数据块0~2成功\n\n");
            }else{
                log("写数据块0~2失败\n");
                return;
            }
        }else{
            log("写数据块0~2失败\n");
            return;
        }

        //写DSFID命令
        if(api.PC_WriteOneTagDSFID(rf,UID,(byte)1,b_DSFID)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0){
                log("写DSFID成功\n\n");
            }else{
                log("写DSFID失败\n");
                return;
            }
        }else{
            log("写DSFID失败\n");
            return;
        }

        //写AFI命令
        if(api.PC_WriteOneTagAFI(rf,UID,(byte)1,b_AFI)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0){
                log("写AFI成功\n\n");
            }else{
                log("写AFI失败\n");
                return;
            }
        }else{
            log("写AFI失败\n");
            return;
        }

        //检测EAS命令、启用EAS命令、禁用EAS命令
        boolean isEAS;//EAS状态
        if(api.PC_CheckOneTagEAS(rf,UID,(byte)1)){
            showSendReceiveData(rf);
            if(rf.RecvData[5]==0){
                log("检测EAS成功\n");
                if(rf.RecvData[1]==(byte)0x0a){//通过检测包的长度判断EAS是否禁用
                    log("EAS状态：关闭\n\n");
                    isEAS=false;
                }else{
                    log("EAS状态：开启\n\n");
                    isEAS=true;
                }
                //自动调节，通过检测的值决定先禁用还是先启用，不更改标签EAS的原始值
                for(int k=0;k<2;k++){
                    if(isEAS){
                        //禁用EAC
                        if(api.PC_BanOneTagEAS(rf,UID,(byte)1)){
                            showSendReceiveData(rf);
                            if(rf.RecvData[5]==0){
                                log("禁用EAS成功\n\n");
                                isEAS=false;
                                continue;
                            }
                        }else{
                            log("禁用EAS失败\n");
                            return;
                        }

                    }else{
                        //启用EAC
                        if(api.PC_EnableOneTagEAS(rf,UID,(byte)1)){
                            showSendReceiveData(rf);
                            if(rf.RecvData[5]==0){
                                log("启用EAS成功\n\n");
                                isEAS=true;
                                continue;
                            }
                        }else{
                            log("启用EAS失败\n");
                            return;
                        }

                    }
                }
                log("检测完成！\n\n");
            }
        }else{
            log("检测EAS失败\n");
            return;
        }

    }

    /**
     * 输出发送的数据
     * @param sendData 数据
     */
    public void showSendData(byte []sendData)
    {
        String data=HexToStr(sendData,(sendData[1]&0xff)+1,true);
        log("发送>> "+data);
    }

    /**
     * 输出接收的数据
     * @param receiveData 数据
     */
    public void showReceiveData(byte[] receiveData)    {
        String data=HexToStr(receiveData,(receiveData[1]&0xff)+1,true);
        log("接收<< "+data);
    }

    /**
     * 输出发送和接收的数据
     * @param rfdata 数据
     */
    public void showSendReceiveData(RFdata rfdata) {
        showSendData(rfdata.SendData);
        showReceiveData(rfdata.RecvData);
    }

    /**
     * 字节数组转字符串
     * @param data 字节数组
     * @param len 要转换的长度
     * @param ishex 是否转换成16进制形式的字符串
     * @return
     */
    private String HexToStr(byte []data,int len,boolean ishex) {
        String strData="";
        for(int i = 0; i < len; i++) {
            if(ishex) {
                strData = strData + String.format("%02X ", data[i]);//十六进制
            }else{
                strData = strData + String.format("%d ", data[i]&0xff);//十进制
            }
        }
        return strData;
    }

    /**
     * 盘点标签
     * @param api PC_API实例对象
     * @param antNum 要打开的天线口号(0~30，u单天线盘点)，0表示不打开（多天线盘点）
     * @param isUploadAntNum 是否开启了上传天线编号（只有网络盘点用到这个参数）
     * @return 标签列表
     */
    public List<TagInfo> ScanTab(PC_API api,int antNum,boolean isUploadAntNum){
        List<TagInfo> tab_list=new ArrayList<TagInfo>();
        RFdata rf_1=new RFdata();
        byte scanType=0;
        if(antNum>=1&&antNum<=30)
        {
            //单标签盘点,打开指定天线口
            if(api.PC_OpenAnt_One(rf_1,(byte)antNum)){
                showSendReceiveData(rf_1);
                log(String.format("打开天线口%d成功！\n",antNum));
                scanType=0x04;
            }else{
                return null;
            }

        }
        switch(api.GetLinkType())
        {
            case PC_API.NET:
            {
                Vector<byte[]> list_pack =new Vector<byte[]>();
                if(api.PC_NETinventoryTag(list_pack,rf_1,scanType)){
                    showSendData(rf_1.SendData);//输出发送数据
                    int len=list_pack.size();
                    for(int i=0;i<len;i++){
                        byte[] pack=list_pack.get(i);
                        int packLen=pack[1]&0xff;
                        if(packLen!=9){
                            //数据包含天线编号
                            int pos=8;//标签信息开始的位置
                            while(pos+9<packLen){//如果下标pos往后的pack数据长度小于一个标签信息的长度，说明标签读取完了
                                TagInfo tag_info=new TagInfo();
                                //获取DSFID
                                tag_info.DSFID=pack[pos];
                                //获取uid
                                for(int k=0;k<8;k++){
                                    tag_info.UID[k]=pack[k+pos+1];
                                }
                                //获取天线口，设置了上传天线编号才能获取到天线口
                                if (isUploadAntNum) {
                                    if(antNum==0) {
                                        tag_info.Ant = pack[pos + 9] & 0xff;
                                    }else {
                                        tag_info.Ant = antNum;
                                    }
                                    pos = pos + 10;//下一个标签的开始位置（因为信息包含了一个字节的天线口）
                                } else {
                                    if(antNum==0) {
                                        tag_info.Ant = 1;
                                    }else {
                                        tag_info.Ant = antNum;
                                    }
                                    pos = pos + 9;//下一个标签的开始位置
                                }
                                tab_list.add(tag_info);
                            }
                        }
                        showReceiveData(pack);//输出接收数据
                    }
                }else{
                    return null;
                }
            }
            break;
            case PC_API.USB://USB和串口盘点方式一样
            case PC_API.COM:
            {
                if(api.PC_InventoryTag(rf_1,scanType)){
                    showSendData(rf_1.SendData);
                    //
                    while((rf_1.RecvData[1]&0xff)>7){
                        showReceiveData(rf_1.RecvData);
                        //从数据包中获取DSFID
                        TagInfo tag_info=new TagInfo();
                        tag_info.DSFID=rf_1.RecvData[6];
                        //获取天线口，设置了上传天线编号才能获取到天线口
                        if(antNum==0) {
                            if (rf_1.RecvData[1] == 0x11) {//通过包的长度判断是否包含天线口数据，设置了上传天线编号数据包多一个字节
                                tag_info.Ant = rf_1.RecvData[15] & 0xff;
                            } else {
                                tag_info.Ant = 1;
                            }
                        }else{
                            tag_info.Ant = antNum;
                        }
                        //获取uid
                        for(int i=0;i<8;i++){
                            tag_info.UID[i]=rf_1.RecvData[i+7];
                        }
                        tab_list.add(tag_info);
                        //继续接收,直到接收到结束包为止
                        if(!api.PC_Receive(rf_1))
                            break;
                    }
                    showReceiveData(rf_1.RecvData);
                }
            }
            break;
        }
        return tab_list;
    }

}